/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package prototype.communication;

import java.awt.AWTEvent;
import java.awt.Event;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import prototype.communication.events.CommunicationEvent;
import prototype.communication.events.CommunicationEventListener;

/**
 *
 * @author Server
 */
public class Receiver implements Runnable {

    private InputStream inputStream;
    private boolean receiving;
    private List<Message> messages = new ArrayList<Message>();
    private List<CommunicationEventListener> eventListeners = new ArrayList<CommunicationEventListener>();

    Receiver(InputStream inputStream) {
        this.inputStream = inputStream;
    }

    private void startReceiving() {
        while (isReceiving()) {
            Message m = readMessage();
            if (m != null) {
                synchronized (this) {
                    messages.add(m);
                    fireCommunicationEvent(CommunicationEvent.MessageReceived);
                }
            }
        }
        try {
            inputStream.close();
        } catch (IOException ex) {
            Logger.getLogger(Receiver.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void run() {
        receiving = true;
        startReceiving();
    }

    public boolean isReceiving() {
        return receiving;
    }

    public void stopReceiving() {
        receiving = false;
    }

    private Message readMessage() {
        Message m = null;
        try {
            m = (Message) (new ObjectInputStream(inputStream)).readObject();
        } catch (IOException ex) {
            Logger.getLogger(Receiver.class.getName()).log(Level.SEVERE, null, ex);
            stopReceiving();
            fireCommunicationEvent(CommunicationEvent.ConnectionLost);
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(Receiver.class.getName()).log(Level.SEVERE, null, ex);
            stopReceiving();
            fireCommunicationEvent(CommunicationEvent.ConnectionLost);
        }
        return m;
    }

    public Message getNextMessage() {
        if (messages.isEmpty()) {
            return null;
        } else {
            Message m = messages.get(0);
            synchronized (this) {
                messages.remove(0);
            }
            return m;
        }
    }

    public synchronized void addEventListener(CommunicationEventListener l) {
        eventListeners.add(l);
    }

    public synchronized void removeEventListener(CommunicationEventListener l) {
        eventListeners.remove(l);
    }

    private synchronized void fireCommunicationEvent(int eventType) {
        CommunicationEvent mood = new CommunicationEvent(this, eventType);
        Iterator listeners = eventListeners.iterator();
        while (listeners.hasNext()) {
            ((CommunicationEventListener) listeners.next()).communicationEventReceived(mood);
        }
    }
}

